
'''
Python 中的协程（Coroutine）是一种用于实现并发编程的方式，它允许程序在执行过程中暂停并在之后恢复执行，
而不会丢失当前的执行上下文。

协程可以在单个线程中运行，通过调度机制实现并发，降低了多线程环境下的上下文切换开销，提高了程序的执行效率。
以下是关于 Python 协程的一些关键点：

定义：协程通常使用 async def 语句来定义。当函数前加上 async 关键字时，这个函数就变成了一个协程函数，
调用它会返回一个协程对象，但不会立即执行其内部代码。

等待：在一个协程内可以使用 await 表达式来等待另一个协程完成。
只有标记为 awaitable 的对象才能被 await，比如其他协程、任务或者由 asyncio 库提供的特殊对象。

并发执行：为了并发地执行多个协程，可以使用 asyncio.gather() 或者创建 asyncio.Task 
对象将协程封装成任务并排入事件循环中执行。

事件循环：协程需要在事件循环中运行。asyncio 是 Python 标准库中用来编写异步应用程序的基础，
提供了事件循环和其他工具来管理协程的执行。


从 Python 3.5 开始引入了 async 和 await 语法糖，
使得协程的定义和使用更加直观。尽管如此，协程仍然保留了可以通过 yield 来暂停和恢复执行的能力，
这与生成器的工作方式相似。

优点：对于 I/O 密集型任务（如网络请求、文件读写等），协程能显著提高效率；由于不需要线程切换，
所以也减少了锁机制的需求。

缺点：对于 CPU 密集型任务，协程的效果可能不佳，因为它们不能利用多核处理器的优势。在这种情况下，
通常建议结合多进程和协程来优化性能。

综上所述，协程提供了一种轻量级且高效的并发编程模型，特别适合处理大量的 I/O 操作或网络请求。
随着 Python 版本的更新，对协程的支持也在不断增强和完善。

单线程中，用协程来进行调度执行和暂停。

'''
import asyncio

async def func1():
    print('func1')
    await asyncio.sleep(10)  # 等待10秒后，再继续执行后面的代码
    print('func1 end')

async def func2():
    print('func2')
    await asyncio.sleep(20)  # 等待20秒后，再继续执行后面的代码
    print('func2 end')

async def func3():
    print('func3')
    await func2()  # 等待func2执行完毕，然后继续执行后面的代码
    print('func3 end')

async def main():
    print('Hello ...')
    await func1()  # 等待func1执行完毕，然后继续执行func2
    await func2()  # 等待func2执行完毕，然后继续执行func3
    await func3()  # 等待func3执行完毕，然后继续执行func4
    print('... World!')

# Python 3.7+
asyncio.run(main())

async def fetch(url):
    print(f"请求 {url}")
    await asyncio.sleep(2)  # 模拟网络请求
    return f"{url} 的响应"

async def main():
    tasks = [fetch(f"url_{i}") for i in range(3)]
    results = await asyncio.gather(*tasks)  # 并发执行
    print(results)

asyncio.run(main())